<template>
  <div style="width: 100%; height: 100%; position: relative">
    <div
      :class="className"
      :style="{ height: height, width: width, 'z-index': 2 }"
      v-loading="loading"
    />
  </div>
</template>

<script>
import resize from "./mixins/resize";
import variables from "@/assets/styles/element-variables.scss";
const xAxisLabelActiveColor = variables.theme; //x轴坐标label选中颜色
const xAxisLabelDefaultColor = "#7D8292"; //x轴坐标label默认颜色

export default {
  mixins: [resize],
  props: {
    className: {
      type: String,
      default: "chart",
    },
    width: {
      type: String,
      default: "100%",
    },
    height: {
      type: String,
      default: "100%",
    },
    option: {
      type: Object,
      default: () => {},
      required: true,
    },
  },
  data() {
    return {
      chart: null,
      loading: true,
      xAxisLabelActives: [], // 横坐标选中的对象
      currentDatazoom: null, //当前缩放大小及位置
    };
  },
  watch: {
    option: {
      deep: true,
      immediate: true,
      handler(val) {
        if (val) {
          this.initChart();
        }
      },
    },
  },
  mounted() {
    this.initChart();
  },
  beforeDestroy() {
    if (!this.chart) {
      return;
    }
    this.chart.off("click");
    this.chart.dispose();
    this.chart = null;
  },
  methods: {
    initChart() {
      if (!this.$el) {
        return;
      }

      const el = this.$el.getElementsByClassName(this.className)[0];
      if (!el) {
        return;
      }

      if (!this.chart) {
        this.chart = this.$echarts.init(el);

        this.initEvent();
      }

      this.setOptions();
    },
    initEvent() {
      this.chart.off("click");

      // echart横坐标点击事件
      this.chart.on("click", "xAxis.category", (e) => {
        if (e.componentType == "xAxis") {
          this.handlexAxisLabelChange(e.value);
        }
      });

      // echart全图点击事件
      this.chart.getZr().on("click", (param) => {
        // 获取 点击的 触发点像素坐标
        const pointInPixel = [param.offsetX, param.offsetY];
        // 判断给定的点是否在指定的坐标系或者系列上
        if (this.chart.containPixel("grid", pointInPixel)) {
          // 获取到点击的 x轴 下标  转换为逻辑坐标
          const xIndex = this.chart.convertFromPixel(
            { seriesIndex: 0 },
            pointInPixel
          )[0];
          const _xIndex = Math.abs(xIndex);
          this.handlexAxisLabelChange(
            this.option.xAxis.data[_xIndex].value,
            _xIndex
          );
        }
      });

      // echart全图移入鼠标事件
      this.chart.getZr().on("mousemove", (params) => {
        const pointInPixel = [params.offsetX, params.offsetY];
        if (this.chart.containPixel("grid", pointInPixel)) {
          // 将此区域的 鼠标样式变为 小手
          this.chart.getZr().setCursorStyle("pointer");
        }
      });

      // 有缩放组件时，监听滚动事件
      if (this.option.dataZoom?.length > 0) {
        this.chart.on("datazoom", (e) => {
          if (e.batch?.length) {
            this.currentDatazoom = {
              start: e.batch[0].start,
              end: e.batch[0].end,
            };
          } else {
            this.currentDatazoom = {
              start: e.start,
              end: e.end,
            };
          }
        });
      }
    },
    // 参数：resetDataZoom：是否重新设置dataZoom，为false则定位到上一次的位置
    setOptions({ resetDataZoom } = { resetDataZoom: true }) {
      // 更新options时，重置xAxisLabelActives选中值
      this.xAxisLabelActives = [];

      let option = {
        color: [
          "#5470c6",
          "#91cc75",
          "#fac858",
          "#ee6666",
          "#73c0de",
          "#3ba272",
          "#fc8452",
          "#9a60b4",
          "#ea7ccc",
        ],
        ...this.option,
      };

      this.chart.setOption(option);

      if (!resetDataZoom && this.currentDatazoom) {
        // 若被移动过，则更新数据时，定位到上一次移动的位置
        this.chart.dispatchAction({
          type: "dataZoom",
          start: this.currentDatazoom.start,
          end: this.currentDatazoom.end,
        });
      } else {
        // 重置位置
        this.currentDatazoom = null;
      }

      this.loading = false;
    },
    handlexAxisLabelChange(value, index = null) {
      // 是否已选中
      const existIndex = this.xAxisLabelActives.findIndex(
        (ele) => ele.value == value
      );

      // 第几项数据
      if (index == null) {
        index = this.option.xAxis.data.findIndex((ele) => ele.value == value);
      }

      // 修改选中状态的样式
      let dataValue = this.option.xAxis.data[index];
      if (existIndex == -1) {
        // 标签label样式设置
        if (typeof dataValue == "string") {
          this.option.xAxis.data.forEach((ele, i) => {
            if (i == index) {
              ele = `{active|${dataValue}}`;
            } else {
              ele = dataValue.replace(/(^{active\|)|(}$)/g, "");
            }
          });
        } else {
          this.option.xAxis.data.forEach((ele, i) => {
            if (i == index) {
              ele.textStyle = {
                color: xAxisLabelActiveColor,
                fontWeight: "600",
              };
            } else {
              ele.textStyle = {
                color: xAxisLabelDefaultColor,
                fontWeight: "normal",
              };
            }
          });
        }
        // 选中的背景颜色
        if (this.option.series[0]?.markArea) {
          const chartWidth = this.chart.getWidth();
          const x1 =
            (index *
              (chartWidth - this.option.grid.left - this.option.grid.right)) /
              this.option.xAxis.data.length +
            this.option.grid.left;
          const x2 =
            ((index + 1) *
              (chartWidth - this.option.grid.left - this.option.grid.right)) /
              this.option.xAxis.data.length +
            this.option.grid.left;
          this.option.series[0].markArea.data = [[{ x: x1 }, { x: x2 }]];
        }
        // 设置拐点样式（空心的数据点，选中时改为实心）
        this.option.series.forEach((ele) => {
          if (typeof ele.data[index] === "object") {
            if (
              [undefined, "emptyCircle"].includes(ele.symbol) ||
              [undefined, "emptyCircle"].includes(ele.data[index].symbol)
            ) {
              ele.data.forEach((d, di) => {
                if (di == index) {
                  d.symbol = "circle";
                } else {
                  d.symbol = "emptyCircle";
                }
              });
            }
          }
        });

        // 记录选中结果
        this.xAxisLabelActives = [
          {
            ...this.option.xAxis.data[index],
          },
        ];

        this.$emit(`active-xAxis-change`, this.xAxisLabelActives, index);
      }

      // 滚动条定位到上一次的位置
      this.setOptions({ resetDataZoom: false });
    },
  },
};
</script>
<style lang="scss" scoped>
@import "../../../../assets/styles/element-variables";
.xAxis-active-icon {
  width: 0;
  height: 0;
  border-top: 8px solid transparent;
  border-left: 8px solid transparent;
  border-right: 8px solid transparent;
  border-bottom: 8px solid $--color-primary;
  border-radius: 3px;
  transform: translate(-50%, -50%);
  z-index: 1;
}
</style>
